package cn.yll.common.utils;

import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Supplier;

/**
 * 多线程异步工具类
 * @author yangll
 */
public class MyAsyncUtil {
    /**
     * 构建50个线程数的固定线程数线程池，池缓冲区大小200，超过的拒绝
     */
    private static final ExecutorService service = new ThreadPoolExecutor(200, 200, 60L, TimeUnit.SECONDS, new LinkedBlockingQueue<>(200), new MyThreadFactory(), new ThreadPoolExecutor.AbortPolicy());

    /**
     * 带返回值
     */
    public static <T> Future<T> submit(Callable<T> callable) {
        return service.submit(callable);
    }

    /**
     * 不带返回值
     */
    public static void run(Runnable run) {
        service.submit(run);
    }

    /**
     * 不带返回值
     */
    public static void runAsync(Runnable runnable) {
        CompletableFuture.runAsync(runnable, service);
    }

    /**
     * 带返回值
     */
    public static <U> CompletableFuture<U> apply(Supplier<U> supplier) {
        return CompletableFuture.supplyAsync(supplier, service);
    }

    /**
     * 创建线程名未xty-async-task-pool开头的线程工厂
     */
    private static class MyThreadFactory implements ThreadFactory {

        private static final AtomicInteger poolNumber = new AtomicInteger(1);
        private final ThreadGroup group;
        private final AtomicInteger threadNumber = new AtomicInteger(1);
        private final String namePrefix;

        MyThreadFactory() {
            SecurityManager s = System.getSecurityManager();
            group = (s != null) ? s.getThreadGroup() :
                    Thread.currentThread().getThreadGroup();
            namePrefix = "async-task-" +
                    poolNumber.getAndIncrement() +
                    "-";
        }

        public Thread newThread(Runnable r) {
            Thread t = new Thread(group, r,
                    namePrefix + threadNumber.getAndIncrement(),
                    0);
            if (t.isDaemon()) {
                t.setDaemon(false);
            }
            if (t.getPriority() != Thread.NORM_PRIORITY)
                t.setPriority(Thread.NORM_PRIORITY);
            return t;
        }
    }
}
